#lang racket

(define (accumulate op initial sequence)
  (if (null? sequence)
      initial
      (op (car sequence)
          (accumulate op initial (cdr sequence)))))

(define (accumulate-n op init seqs)
  (if (null? (car seqs))
      '()
      (cons (accumulate op init (map car seqs))
            (accumulate-n op init (map cdr seqs)))))

(define (dot-product v w)
  (accumulate + 0 (map * v w)))

(define  (transpose mat)
  (accumulate-n cons '() mat))

(define (matrix-*-vector m v)
  (map (lambda (x) (dot-product x v)) m))

(define (matrix-*-matrix m n)
  (let ((cols (transpose n)))
    (map (lambda (x) (matrix-*-vector cols x)) m)))

;TESTING---------------------------------------------------------------------------------------------

(define a (list (list 1 2 2) (list 5 7 3) (list 4 9 3)))

(define b (list 3 2 3))

(matrix-*-vector a b)

(define c (list (list 0 1 2) (list 4 2 3) (list 5 3 1)))

(define d (list (list 3 1 1) (list 1 3 1) (list 4 0 2)))

(matrix-*-matrix c d)

(define matrix (list (list 1 2 3 4) (list 4 5 6 6) (list 6 7 8 9)))

(transpose matrix)